import os
import argparse

import pandas as pd
import requests
import json
import numpy as np
from datetime import datetime
from iotdb.Session import Session
from iotdb.utils.BitMap import BitMap
from iotdb.utils.IoTDBConstants import TSDataType, TSEncoding, Compressor
from iotdb.utils.Tablet import Tablet
from iotdb.utils.NumpyTablet import NumpyTablet

from system.predict_csv import start_application
from system.process_phm_csv import process_data

# ThingsBoard设备访问令牌
ACCESS_TOKEN_BEARING1_3 = 'HftfNklEgEvNJxMAS4ao'
ACCESS_TOKEN_RUL = 'yxvr73ub1chijcqy7soi'

# ThingsBoard服务器URL
THINGSBOARD_URL = 'http://127.0.0.1:8080/api/v1/'

def import_data():
    # creating session connection.
    ip = "127.0.0.1"
    port_ = "6667"
    username_ = "root"
    password_ = "root"
    session = Session(ip, port_, username_, password_, fetch_size=1024, zone_id="UTC+8", enable_redirection=True)

    session.open(False)

    start_time = datetime(2024, 1, 1, 16, 33, 1)
    end_time = datetime(2024, 1, 1, 16, 33, 2)

    start_timestamp = int(start_time.timestamp() * 1000)
    end_timestamp = int(end_time.timestamp() * 1000)

    result = session.execute_query_statement("select * from root.phm2012.no1.Bearing1_3 WHERE time >= " + str(start_timestamp) + " AND time < " + str(end_timestamp))
    data = result.todf()

    if len(data) > 2560:
        data_chunks = [data.iloc[i:i + 2560].copy() for i in range(0, len(data), 2560)]
    else:
        data_chunks = [data]
    data_chunks = np.stack([chunk.values for chunk in data_chunks])

    session.close()
    return data_chunks

def calculate_mean_every_100_rows(data):
    # Calculate the mean of every 100 rows for each column
    result = data.groupby(data.index // 100).mean()
    return result

def send2thingsboard(datas):
    # data = pd.DataFrame(mean_data)
    messages = []
    for index, data in datas.iterrows():
        message = {
            'ts': data[0],
            "values": {
                "horizontal": data[1],
                "vertical": data[2]
            }
        }
        # message = {
        #     "horizontal": data[1],
        #     "vertical": data[2]
        # }
        messages.append(message)
    url = f"{THINGSBOARD_URL}{ACCESS_TOKEN_BEARING1_3}/telemetry"
    response = requests.post(url, data=json.dumps(messages), headers={'Content-Type': 'application/json'})
    if response.status_code == 200:
        print(f"Data sent successfully")
    else:
        print(f"Failed to send data for index {index}: {response.status_code} - {response.text}")

def send2thingsboard_rul(datas):
    messages = []
    for data in datas:
        message = {
            'ts': data[0],
            "values": {
                "rul": data[1]
            }
        }
        messages.append(message)
    url = f"{THINGSBOARD_URL}{ACCESS_TOKEN_RUL}/telemetry"
    response = requests.post(url, data=json.dumps(messages), headers={'Content-Type': 'application/json'})
    if response.status_code == 200:
        print(f"Data sent successfully")
    else:
        print(f"Failed to send data: {response.status_code} - {response.text}")


def parse_args():
    parser = argparse.ArgumentParser()

    parser.add_argument("--data-path", type=str, dest="data_path", default="./system/data/system_csv/",
                        help="set the direction path of ptm dataset")
    parser.add_argument("--model-name", type=str, dest="model_name",
                        choices=["convTransformer", "seq2seq", "pyraformer", "informer", "lstm", "gru", "transformer",
                                 "crate", "mtct"],
                        help="set the model to be trained, model name must be in one of convTransformer, seq2seq, pyraformer, informer, lstm, gru, crate")
    parser.add_argument("--model-path", type=str, dest="model_path", default="./system/model",
                        help="set the path of model to be loaded")
    parser.add_argument("--save-path", type=str, dest="save_path", default="./system/predict_result",
                        help="set the saved model direcation path")
    parser.set_defaults(prep=True)

    return parser.parse_args()

if __name__ == '__main__':
    args = parse_args()
    model_name = args.model_name
    data_path = args.data_path
    save_path = args.save_path
    model_path = args.model_path

    model_path = os.path.join(model_path, model_name)
    raw_datas = import_data()
    # y_pred_list = [(1704042000000.0, 0.9996562004089355), (1704045600000.0, 1.0009387731552124),
    #                (1704049200000.0, 1.001204252243042),
    #                (1704052800000.0, 1.00319242477417)]
    y_pred_list = []
    for raw_data in raw_datas:
        raw_data = pd.DataFrame(raw_data, columns=['Time', 'horizontal', 'vertical'])
        # mean_data = calculate_mean_every_100_rows(raw_data)
        send2thingsboard(raw_data)


        time = raw_data['Time'][0]
        start_time = datetime(2024, 1, 1, 0, 0, 0)
        start_timestamp = int(start_time.timestamp() * 1000)
        hours_since_start = (time - start_timestamp) / 3600000
        raw_data = raw_data.iloc[:, 1:]
        data = process_data(raw_data, hours_since_start)
        y_pred = start_application(model_name, model_path, data_path, save_path, data)
        y_pred_list.append((time, y_pred))
        print(f"time = {time} ,y_pred = {y_pred}")
    print(y_pred_list)
    send2thingsboard_rul(y_pred_list)